package jeudelavie.modele;

import ObservableObserveur.Observable;
import ObservableObserveur.Observateur;
import java.util.ArrayList;

public class Cellule implements Observable{
    private int x,y, etatPrecedent, etatSuivant,voisinsVivants,voisinsVivantsFutur;
    private ArrayList<Cellule> voisins;
    private ArrayList<Observateur> listeObservateurs;
    
    //Constructeurs
    
    Cellule(int x, int y){
        this.x = x;
        this.y = y;
        if(Math.random()<0.5){
            this.etatPrecedent=1;
        }
        else{
            this.etatPrecedent=0;
        }
        this.etatSuivant=-1;
        this.voisins=new ArrayList<>();
        this.voisinsVivants=0;
        this.voisinsVivantsFutur=0;
        this.listeObservateurs = new ArrayList<>();
    }
    
    Cellule(int x, int y,int etat){
        this.x=x;
        this.y=y;
        this.etatPrecedent=etat;
        this.voisins=new ArrayList<>();
        this.etatSuivant=-1;
        this.voisinsVivants=0;
        this.voisinsVivantsFutur=0;
        this.listeObservateurs = new ArrayList<>();        
    }
    
    
    //Accesseurs et Mutateurs
    public int getVoisinsVivants() {
        return voisinsVivants;
    }
    
    public void incrementeVoisinsVivantsFutur(){
        this.setVoisinsVivantsFutur(this.getVoisinsVivantsFutur() + 1);
    }
    
    public void decrementeVoisinsVivantsFutur(){
        this.setVoisinsVivantsFutur(this.getVoisinsVivantsFutur() - 1);
    }
    
    public void setVoisinsVivants(int voisinsVivants) {
        this.voisinsVivants = voisinsVivants;
    }
        
    public int getVoisinsVivantsFutur() {
        return voisinsVivantsFutur;
    }

    public ArrayList<Cellule> getVoisins() {
        return voisins;
    }
    
    
    public int getX(){
        return this.x;
    }
    
    public int getY(){
        return this.y;
    }      

    public int getEtatPrecedent(){
        return etatPrecedent;
    }

    public void setEtatPrecedent(int etatPrecedent) {
        this.etatPrecedent = etatPrecedent;
    }

    public int getEtatSuivant() {
        return etatSuivant;
    }
    
    public void setEtatSuivant(int etatSuivant) {
        this.etatSuivant = etatSuivant;
    }
    
    public void setVoisinsVivantsFutur(int voisinsVivantsFutur) {
        this.voisinsVivantsFutur = voisinsVivantsFutur;
    }
    
   //Stocke l'état suivant de la cellule
    public void majEtat(){
        etatSuivant = this.calculeEtatSuivant();
    }
    
    //Calcule l'état suivant de la cellule (vivante ou morte)
    public int calculeEtatSuivant(){
       int etat;
       if (this.etatPrecedent==1){
            if((this.getVoisinsVivants()<2)||(this.getVoisinsVivants()>3)){
                etat=0;
            }
            else{
                etat=1;
            }           
       }
       else
       {
           if (this.etatPrecedent==0){
               if(this.getVoisinsVivants()==3)
               {
                   etat = 1;
               }
               else
               {
                   etat = 0 ;
               }
           }
           else
           {
               etat = -1;
           }
       }
       return etat;
    }
    
    //Permet de créer le voisinage de la cellule
    public void ajouteVoisin(Cellule c){
        this.getVoisins().add(c);
    }
  
    //Met à jour l'état actuel avec l'etat suivant pour passer à la génération suivante
    public void switchEtat() {
        this.etatPrecedent=this.etatSuivant;
        this.voisinsVivants=this.voisinsVivantsFutur;
    }

    //Cherche dans l'ensemble des voisins pour voir le nombre de vivants
    public void calculerVoisinsVivants(){
        this.voisinsVivants = 0;
        
        for(Cellule c : this.getVoisins())
        {
            if(c.getEtatPrecedent()==1){this.voisinsVivants++;}
        }
    }
    
    //Fonctions de gestion des Observateurs
    @Override
    public void ajouterObservateur(Observateur o) {
        this.listeObservateurs.add(o);
    }

    @Override
    public void notifierObservateur() {
        for (Observateur o : this.listeObservateurs)
        {
            o.actualiser(this);
        }
    }

    @Override
    public void supprimerObservateur() {
        this.listeObservateurs.clear();
    }
}
